//Globals we need
local table = table
local pairs = pairs
local assert = assert
local type = type
local RealTime = RealTime
local hook = hook
local unpack = unpack
local pcall = pcall
local Msg = Msg
local string = string

module("ptimer")
local isRunning = false
local intCounter = 0
local intSimpleCounter = 0
local PTimers = {}
local strCurrentGroup = "COMMON"

local function checktimers()
	//1st lets check the timers
	for groupkey, groupvalue in pairs(PTimers) do
		for i, v in pairs(groupvalue) do
			if !v.PAUSED then
				if RealTime() - v.LastRan >= v.Interval then
					local run, error = pcall(v.Func, unpack(v.Args))
					if !run then Msg("PTIMER ERROR:" .. error .. "\n") end
					v.LastRan = RealTime()
					v.TimesRan = v.TimesRan + 1
				end
				if v.TimesRan >= v.Rep && v.Rep != 0 then
					PTimers[groupkey][i] = nil //Kill the timer
					intCounter = intCounter - 1
				end
			end
		end
	end
	if intCounter <= 0 then
		hook.Remove("Think","PTimerCheck")
	end
end

function Add(strID, intInterval, intRep, fnCallback, ...)
	//Asserts to make sure the values are what they are suppose to be
	assert(type(strID) == "string","Non-String ID")
	assert(type(intInterval) == "number","Non-Number Interval")
	assert(type(intRep) == "number", "Non-Number Repetition")
	assert(type(fnCallback) == "function", "Callback is not a Function!")
	
	local tblNewTimer = {}
	
	tblNewTimer.Interval = intInterval
	tblNewTimer.Rep = intRep
	tblNewTimer.Func = fnCallback
	tblNewTimer.Args = arg
	tblNewTimer.TimesRan = 0
	tblNewTimer.PAUSED = false
	tblNewTimer.LastRan = RealTime()
	
	if PTimers[strCurrentGroup] == nil then PTimers[strCurrentGroup] = {} end
	
	PTimers[strCurrentGroup][strID] = tblNewTimer
	intCounter = intCounter + 1
	
	if !isRunning then
		hook.Add("Think", "PTimerCheck", checktimers)
		isRunning = true
	end
end

//Removes a Running Timer
function Remove(strID, strGroup)
	strGroup = strGroup or "COMMON"
	PTimers[strGroup][strID] = nil
	intCounter = intCounter - 1
end

function Simple(intInterval, fnCallback, ...)
	intSimpleCounter = intSimpleCounter + 1
	Add("PTimer" .. intSimpleCounter, intInterval, 1, fnCallback, unpack(arg))
end

function PurgeAllTimers() //Yes I know this can be used badly,
	PTimers = {}
	intCounter = 0
	intSimpleCounter = 0
	isRunning = false
end

function SetGroup(strID)
	if strID == nil then 
		strCurrentGroup = "COMMON" 
		return
	end
	strCurrentGroup = string.upper(strID)	
end

function RemoveGroup(strID)
	strID = string.upper(strID)
	for i, _ in pairs(PTimers[strID]) do
		Remove(i, strID)
	end
end

function IsTimer(strID, strGroup)
	strGroup = strGroup or "COMMON"
	strGroup = string.upper(strGroup)
	
	if PTimers[strGroup] then
		if PTimers[strGroup][strID] then
			return true
		else
			return false
		end
	else
		return false
	end
end

function IsGroup(strGroup)
	strGroup = strGroup or "COMMON"
	strGroup = string.upper(strGroup)
	
	if PTimers[strGroup] then
		return true
	else
		return false
	end
end
function Pause(strID, strGroup)
	strGroup = strGroup or "COMMON"
	strGroup = string.upper(strGroup)
	
	PTimers[strGroup][strID].PAUSED = true
end
Stop = Pause

function UnPause(strID, strGroup)
	strGroup = strGroup or "COMMON"
	strGroup = string.upper(strGroup)
	
	PTimers[strGroup][strID].PAUSED = false
end
Start = UnPause

function PauseGroup(strID)
	strID = string.upper(strID)
	for i, _ in pairs(PTimers[strID]) do
		Pause(i, strID)
	end
end
StopGroup = PauseGroup

function UnPauseGroup(strID)
	strID = string.upper(strID)
	for i, _ in pairs(PTimers[strID]) do
		UnPause(i, strID)
	end
end
StartGroup = UnPauseGroup





